"""
插件管理服务层
"""
from apps.extensions import db
from apps.modules.admin.models.sys.sys_plugin import SysPlugin, SysPluginLog
from apps.modules.admin.schemas.sys.sys_plugin import (
    SysPluginCreateSchema, SysPluginUpdateSchema, SysPluginQuerySchema,
    SysPluginLogSchema, SysPluginLogQuerySchema
)
from apps.extensions.PluginManager import (
    enable_plugin
)
from datetime import datetime
import os
import hashlib
from typing import Dict, List, Optional, Tuple
import json
import logging

logger = logging.getLogger(__name__)

class PluginService:
    """插件管理服务类"""
    
    @staticmethod
    def create_plugin(data: Dict) -> Tuple[bool, str, Optional[SysPlugin]]:
        """创建插件"""
        try:
            # 验证数据
            # schema = SysPluginCreateSchema()
            # validated_data = schema.load(data)
            # 读取插件配置
            config = None
            try:
                config_path = os.path.join(data, 'plugin.json')
                with open(config_path, 'r', encoding='utf-8') as f:
                    config = json.load(f)
            except Exception as e:
                logger.error(f"加载插件配置失败: {e}")
            # 检查插件名称是否已存在
            existing_plugin = SysPlugin.query.filter_by(name=config['name']).first()
            if existing_plugin:
                return False, f"插件名称 '{data['name']}' 已存在", None

            # 创建插件
            sysPlugin = SysPlugin(
                name=config['name'],
                version=config['version'],
                description=config['description'],
                author=config['author'],
                is_installed = True
            )
            db.session.add(sysPlugin)
            db.session.commit()
            enable_plugin(plugin_name=config['name'])
            return True, "插件创建成功", sysPlugin
            
        except Exception as e:
            print(e)
            db.session.rollback()
            return False, f"创建插件失败: {str(e)}", None
    
    @staticmethod
    def update_plugin(plugin_id: int, data: Dict) -> Tuple[bool, str, Optional[SysPlugin]]:
        """更新插件"""
        try:
            # 查找插件
            plugin = SysPlugin.query.get(plugin_id)
            if not plugin:
                return False, "插件不存在", None
            
            # 验证数据
            schema = SysPluginUpdateSchema()
            validated_data = schema.load(data, partial=True)
            
            # 检查插件名称是否重复（排除自己）
            if 'name' in validated_data:
                existing_plugin = SysPlugin.query.filter(
                    SysPlugin.name == validated_data['name'],
                    SysPlugin.id != plugin_id
                ).first()
                if existing_plugin:
                    return False, f"插件名称 '{validated_data['name']}' 已存在", None
            
            # 更新插件
            for key, value in validated_data.items():
                setattr(plugin, key, value)
            
            plugin.updated_at = datetime.now()
            db.session.commit()
            
            return True, "插件更新成功", plugin
            
        except Exception as e:
            db.session.rollback()
            return False, f"更新插件失败: {str(e)}", None
    
    @staticmethod
    def delete_plugin(plugin_id: int) -> Tuple[bool, str]:
        """删除插件"""
        try:
            plugin = SysPlugin.query.get(plugin_id)
            if not plugin:
                return False, "插件不存在"
            
            # 删除相关日志
            SysPluginLog.query.filter_by(plugin_id=plugin_id).delete()
            
            # 删除插件
            db.session.delete(plugin)
            db.session.commit()
            
            return True, "插件删除成功"
            
        except Exception as e:
            db.session.rollback()
            return False, f"删除插件失败: {str(e)}"
    
    @staticmethod
    def get_plugin_by_id(plugin_id: int) -> Optional[SysPlugin]:
        """根据ID获取插件"""
        return SysPlugin.query.get(plugin_id)
    
    @staticmethod
    def get_plugin_by_name(name: str) -> Optional[SysPlugin]:
        """根据名称获取插件"""
        return SysPlugin.query.filter_by(name=name).first()
    
    @staticmethod
    def get_plugins(query_params: Dict) -> Tuple[List[SysPlugin], int]:
        """获取插件列表"""
        try:
            # 验证查询参数
            # schema = SysPluginQuerySchema()
            # validated_params = schema.load(query_params)
            
            # 构建查询
            query = SysPlugin.query
            
            # 添加过滤条件
            if query_params.get('name'):
                query = query.filter(SysPlugin.name.like(f"%{query_params['name']}%"))
            
            if query_params.get('author'):
                query = query.filter(SysPlugin.author.like(f"%{query_params['author']}%"))

            if query_params.get('status') is not None:
                query = query.filter(SysPlugin.status == query_params['status'])
            
            if query_params.get('is_installed') is not None:
                query = query.filter(SysPlugin.is_installed == query_params['is_installed'])
            
            if query_params.get('is_enabled') is not None:
                query = query.filter(SysPlugin.is_enabled == query_params['is_enabled'])
            
            # 获取总数
            total = query.count()
            
            # 排序
            sort_field = query_params.get('sort_field', 'id')
            sort_order = query_params.get('sort_order', 'desc')
            
            if hasattr(SysPlugin, sort_field):
                order_column = getattr(SysPlugin, sort_field)
                if sort_order == 'desc':
                    order_column = order_column.desc()
                query = query.order_by(order_column)
            
            # 分页
            page = query_params.get('page', 1)
            limit = query_params.get('limit', 20)
            offset = (page - 1) * limit
            
            plugins = query.offset(offset).limit(limit).all()
            
            return plugins, total
            
        except Exception as e:
            return [], 0
    
    @staticmethod
    def enable_plugin(plugin_id: int) -> Tuple[bool, str]:
        """启用插件"""
        try:
            plugin = SysPlugin.query.get(plugin_id)
            if not plugin:
                return False, "插件不存在"
            
            if not plugin.is_installed:
                return False, "插件未安装，无法启用"
            
            if plugin.is_enabled:
                return False, "插件已经启用"
            
            plugin.is_enabled = True
            plugin.enabled_at = datetime.now()
            plugin.status = 1
            db.session.commit()
            
            return True, "插件启用成功"
            
        except Exception as e:
            db.session.rollback()
            return False, f"启用插件失败: {str(e)}"
    
    @staticmethod
    def disable_plugin(plugin_id: int) -> Tuple[bool, str]:
        """禁用插件"""
        try:
            plugin = SysPlugin.query.get(plugin_id)
            if not plugin:
                return False, "插件不存在"
            
            if not plugin.is_enabled:
                return False, "插件已经禁用"
            
            plugin.is_enabled = False
            plugin.enabled_at = None
            plugin.status = 0
            db.session.commit()
            
            return True, "插件禁用成功"
            
        except Exception as e:
            db.session.rollback()
            return False, f"禁用插件失败: {str(e)}"
    
    @staticmethod
    def install_plugin(plugin_id: int) -> Tuple[bool, str]:
        """安装插件"""
        try:
            plugin = SysPlugin.query.get(plugin_id)
            if not plugin:
                return False, "插件不存在"
            
            if plugin.is_installed:
                return False, "插件已经安装"
            
            # 检查插件文件是否存在
            if plugin.plugin_path and not os.path.exists(plugin.plugin_path):
                return False, "插件文件不存在"
            
            plugin.is_installed = True
            plugin.installed_at = datetime.now()
            db.session.commit()
            
            return True, "插件安装成功"
            
        except Exception as e:
            db.session.rollback()
            return False, f"安装插件失败: {str(e)}"
    
    @staticmethod
    def uninstall_plugin(plugin_id: int) -> Tuple[bool, str]:
        """卸载插件"""
        try:
            plugin = SysPlugin.query.get(plugin_id)
            if not plugin:
                return False, "插件不存在"
            
            if not plugin.is_installed:
                return False, "插件未安装"
            
            # 如果插件已启用，先禁用
            if plugin.is_enabled:
                plugin.is_enabled = False
                plugin.enabled_at = None
                plugin.status = 0
            
            plugin.is_installed = False
            plugin.installed_at = None
            db.session.commit()
            
            return True, "插件卸载成功"
            
        except Exception as e:
            db.session.rollback()
            return False, f"卸载插件失败: {str(e)}"
    
    @staticmethod
    def calculate_file_hash(file_path: str) -> str:
        """计算文件哈希值"""
        if not os.path.exists(file_path):
            return ""
        
        hash_md5 = hashlib.md5()
        with open(file_path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        return hash_md5.hexdigest()
    
    @staticmethod
    def get_file_size(file_path: str) -> int:
        """获取文件大小"""
        if not os.path.exists(file_path):
            return 0
        return os.path.getsize(file_path)
    
    @staticmethod
    def create_plugin_log(plugin_id: int, operation: str, operation_desc: str = None,
                         operator: str = None, ip_address: str = None, user_agent: str = None,
                         success: bool = True, error_message: str = None) -> SysPluginLog:
        """创建插件操作日志"""
        try:
            log = SysPluginLog(
                plugin_id=plugin_id,
                operation=operation,
                operation_desc=operation_desc,
                operator=operator,
                ip_address=ip_address,
                user_agent=user_agent,
                success=success,
                error_message=error_message
            )
            db.session.add(log)
            db.session.commit()
            return log
        except Exception as e:
            db.session.rollback()
            return None
    
    @staticmethod
    def get_plugin_logs(query_params: Dict) -> Tuple[List[SysPluginLog], int]:
        """获取插件日志列表"""
        try:
            # 验证查询参数
            schema = SysPluginLogQuerySchema()
            validated_params = schema.load(query_params)
            
            # 构建查询
            query = SysPluginLog.query
            
            # 添加过滤条件
            if validated_params.get('plugin_id'):
                query = query.filter(SysPluginLog.plugin_id == validated_params['plugin_id'])
            
            if validated_params.get('operation'):
                query = query.filter(SysPluginLog.operation.like(f"%{validated_params['operation']}%"))
            
            if validated_params.get('operator'):
                query = query.filter(SysPluginLog.operator.like(f"%{validated_params['operator']}%"))
            
            if validated_params.get('success') is not None:
                query = query.filter(SysPluginLog.success == validated_params['success'])
            
            if validated_params.get('start_date'):
                query = query.filter(SysPluginLog.created_at >= validated_params['start_date'])
            
            if validated_params.get('end_date'):
                query = query.filter(SysPluginLog.created_at <= validated_params['end_date'])
            
            # 获取总数
            total = query.count()
            
            # 排序
            sort_field = validated_params.get('sort_field', 'id')
            sort_order = validated_params.get('sort_order', 'desc')
            
            if hasattr(SysPluginLog, sort_field):
                order_column = getattr(SysPluginLog, sort_field)
                if sort_order == 'desc':
                    order_column = order_column.desc()
                query = query.order_by(order_column)
            
            # 分页
            page = validated_params.get('page', 1)
            limit = validated_params.get('limit', 20)
            offset = (page - 1) * limit
            
            logs = query.offset(offset).limit(limit).all()
            
            return logs, total
            
        except Exception as e:
            return [], 0 